<template>
    <Modal ref="modalRef" class="avatar-upload-modal-root" @afterLeave="clearData">
        <div class="cropper-content">
            <VueCropper ref="cropperRef" :img="cropperOptions.img" :info="true" :infoTrue="cropperOptions.infoTrue"
                :auto-crop="cropperOptions.autoCrop" :fixed-box="cropperOptions.fixedBox"
                :fixedNumber="cropperOptions.fixedNumber" :fixed="cropperOptions.fixed"
                :centerBox="cropperOptions.centerBox" @realTime="realTime">
            </VueCropper>
        </div>
        <div class="pv-content">
            <img v-if="previews.imgBase64" class="pv-avatar" :src="previews.imgBase64" alt="avatar" />
            <div v-else class="empty-img"></div>
        </div>
        <div class="footer-btn">
            <a-button class="cancel-btn" @click="hide">取 消</a-button>
            <a-button type="info" :loading="confirmLoading" @click="confirm">确 认</a-button>
        </div>
    </Modal>
</template>
<script setup lang="ts">
import { ref, reactive, DefineComponent } from 'vue'
import Modal from './modal.vue'
import { VueCropper } from 'vue-cropper'
import 'vue-cropper/dist/index.css'
import { base64toFile } from '../../utils/index.js'

interface CropperOptionsType {
    img: string | ArrayBuffer | null // 裁剪图片的地址
    info: true // 裁剪框的大小信息
    outputSize: number // 裁剪生成图片的质量 [1至0.1]
    outputType: 'jpeg' // 裁剪生成图片的格式
    canScale: boolean // 图片是否允许滚轮缩放
    autoCrop: boolean // 是否默认生成截图框
    autoCropWidth: number // 默认生成截图框宽度
    autoCropHeight: number // 默认生成截图框高度
    fixedBox: boolean // 固定截图框大小 不允许改变
    fixed: boolean // 是否开启截图框宽高固定比例
    fixedNumber: Array<number> // 截图框的宽高比例  需要配合centerBox一起使用才能生效
    full: boolean // 是否输出原图比例的截图
    canMoveBox: boolean // 截图框能否拖动
    original: boolean // 上传图片按照原始比例渲染
    centerBox: boolean // 截图框是否被限制在图片里面
    infoTrue: boolean // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
}

const emit = defineEmits(['success'])
const modalRef = ref<DefineComponent | null>(null)
const cropperRef = ref<DefineComponent | null>(null)
const cropperOptions = reactive<CropperOptionsType>({
    img: '', // 需要剪裁的图片
    autoCrop: true, // 是否默认生成截图框
    autoCropWidth: 300, // 默认生成截图框的宽度
    autoCropHeight: 300, // 默认生成截图框的长度
    fixedBox: false, // 是否固定截图框的大小 不允许改变
    info: true, // 裁剪框的大小信息
    outputSize: 0.7, // 裁剪生成图片的质量 [1至0.1]
    outputType: 'jpeg', // 裁剪生成图片的格式
    canScale: false, // 图片是否允许滚轮缩放
    fixed: true, // 是否开启截图框宽高固定比例
    fixedNumber: [1, 1], // 截图框的宽高比例 需要配合centerBox一起使用才能生效
    full: true, // 是否输出原图比例的截图
    canMoveBox: false, // 截图框能否拖动
    original: false, // 上传图片按照原始比例渲染
    centerBox: true, // 截图框是否被限制在图片里面
    infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高
})
const previews = reactive({
    imgBase64: '',
    imgName: '',
})
const confirmLoading = ref(false)
/**
 * @description: 确认回调
 * @return {void}
 */
function confirm() {
    confirmLoading.value = true
    const file = base64toFile(previews.imgBase64, previews.imgName)
    confirmLoading.value = false
    hide()
    emit('success', file)

}

/**
 * @description: 实时预览事件
 * @param {Object} 文件相关信息
 * @return {void}
 */
function realTime(realTimeData: { url: string }) {
    if (realTimeData.url) {
        cropperRef.value?.getCropData((data: string) => {
            previews.imgBase64 = data
        })
    }
}
/**
 * @description: 清空缓存数据
 * @return {void}
 */
function clearData() {
    previews.imgBase64 = ''
    previews.imgName = ''
    cropperOptions.img = ''
    confirmLoading.value = false
}
/**
 * @description: 显示弹窗处理
 * @param {MenuType | null} 菜单信息
 * @param {Boolean} 新增/修改标识
 * @return {void}
 */
function show(info: { image: string | ArrayBuffer | null; imageName: string }, cropperOption: Partial<CropperOptionsType> | null) {
    cropperOptions.img = info.image
    previews.imgName = info.imageName
    if (cropperOption) {
        Object.keys(cropperOption).forEach((key) => {
            if (key in cropperOptions) {
                ; (cropperOptions as any)[key] = (cropperOption as any)[key]
            }
        })
    }
    modalRef.value?.Show()
}
/**
 * @description: 隐藏弹窗
 * @return {void}
 */
function hide() {
    modalRef.value?.Hide()
    clearData()
}
defineExpose({ show, hide })
</script>
<style scoped lang="scss">
.avatar-upload-modal-root {
    .cropper-content {
        height: 300px;
        width: 100%;
    }

    .pv-content {
        display: flex;
        flex-direction: column;
        justify-content: flex-start;
        align-items: center;

        .pv-avatar {
            margin-top: 11%;
            border-radius: 50%;
            width: 251px;
        }
    }

    .footer-btn {
        display: flex;
        justify-content: flex-end;

        .cancel-btn {
            margin-right: 8px;
        }
    }
}
</style>
